package bsh.meta;

import java.lang.reflect.Modifier;
import java.util.LinkedList;
import java.util.List;

import org.objectweb.asm.MethodVisitor;

import bsh.LocalVariable;
import bsh.asm.acessor.LocalObjectAccessor;
import bsh.compilation.CompilationOptions;
import bsh.compilation.DebugOptions;

/**
 * Escopo para metodo
 * 
 * @author takeshi
 */
public class MethodScope extends ScopeImpl {

    private final MethodDescriptor method;

    private final List<LocalVariable> registered = new LinkedList<LocalVariable>();

    /**
     * @param parent {@link ScopeImpl}
     * @param method {@link MethodDescriptor}
     */
    public MethodScope(ScopeImpl parent, MethodDescriptor method) {
        super(parent, ScopeType.METHOD);
        this.method = method;
        if (!Modifier.isStatic(method.modifiers())) {
            final LocalVariable lv = new LocalVariable("this", 0, method.declaringType(), this.getStartLabel(), this.getEndLabel());
            this.registered.add(lv);
            getAccessors().put("this", new LocalObjectAccessor(lv));
            getVariables().put("this", lv);
        }
    }

    /**
     * @return {@link MethodDescriptor}
     */
    public MethodDescriptor getMethod() {
        return this.method;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "[METHOD  " + this.method.methodName() + "]";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void registerVariable(LocalVariable lv) {
        this.registered.add(lv);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean isInsideConstructor() {
        return this.method.methodName().equals("<init>");
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void installEndLabel(MethodVisitor visitor, CompilationOptions options) {
        super.installEndLabel(visitor, options);
        if (options.debugOptions().contains(DebugOptions.LOCAL_VARIABLES)) {
            for (LocalVariable lv : this.registered) {
                visitor.visitLocalVariable(lv.getName(), lv.getType().typeDescription(), null, lv.getStart(), lv.getEnd(), lv.getOffset());
            }
        }
    }

}
